JVM 优化之调整大内存分页

转自:http://cjjwzs.iteye.com/blog/1059381

本文将从内存分页的原理,如何调整分页大小两节内容,向你阐述 LargePage 对 JVM 的性能有何提升作用,并在文末点明了大内分页的副作用。OK,让我们开始吧!

内存分页大小对性能的提升原理

首先,我们需要回顾一小部分计算机组成原理,这对理解大内存分页至于 JVM 性能的提升是有好处的。

什么是内存分页?

我们知道,CPU 是通过寻址来访问内存的。32 位 CPU 的寻址宽度是 0~0xFFFFFFFF ,计算后得到的大小是 4G,也就是说可支持的物理内存最大是 4G。

但在实践过程中,碰到了这样的问题,程序需要使用 4G 内存,而可用物理内存小于 4G,导致程序不得不降低内存占用。
为了解决此类问题,现代 CPU 引入了 MMU(Memory Management Unit 内存管理单元)。

MMU 的核心思想是利用虚拟地址替代物理地址,即 CPU 寻址时使用虚址,由 MMU 负责将虚址映射为物理地址。
MMU 的引入,解决了对物理内存的限制,对程序来说,就像自己在使用 4G 内存一样。

内存分页 (Paging) 是在使用 MMU 的基础上,提出的一种内存管理机制。它将虚拟地址和物理地址按固定大小(4K)分割成页 (page) 和页帧(page frame),并保证页与页帧的大小相同。

这种机制,从数据结构上,保证了访问内存的高效,并使 OS 能支持非连续性的内存分配。
在程序内存不够用时,还可以将不常用的物理内存页转移到其他存储设备上,比如磁盘,这就是大家耳熟能详的虚拟内存。

在上文中提到,虚拟地址与物理地址需要通过映射,才能使 CPU 正常工作。
而映射就需要存储映射表。在现代 CPU 架构中,映射关系通常被存储在物理内存上一个被称之为页表 (page table) 的地方。page table 在现代操作系统中由全局目录(PGD)- 中间目录(PMD)- 页表项(PTE)三层树构成,有时候不同书上图不一样但意思一样,只是画多画少。

进一步优化,引入 TLB(Translation lookaside buffer,页表寄存器缓冲)

由上一节可知,页表是被存储在内存中的。我们知道 CPU 通过总线访问内存,肯定慢于直接访问寄存器的。
为了进一步优化性能,现代 CPU 架构引入了 TLB,用来缓存一部分经常访问的页表内容。

为什么要支持大内存分页?

TLB 是有限的,这点毫无疑问。当超出 TLB 的存储极限时,就会发生 TLB miss,之后,OS 就会命令 CPU 去访问内存上的页表。如果频繁的出现 TLB miss,程序的性能会下降地很快。

为了让 TLB 可以存储更多的页地址映射关系,我们的做法是调大内存分页大小。

如果一个页 4M,对比一个页 4K,前者可以让 TLB 多存储 1000 个页地址映射关系,性能的提升是比较可观的。

调整 OS 和 JVM 内存分页

在 Linux 和 windows 下要启用大内存页,有一些限制和设置步骤。

Linux:

限制:需要 2.6 内核以上或 2.4 内核已打大内存页补丁。
确认是否支持,请在终端敲如下命令:

1
2
3
4
# cat /proc/meminfo | grep Huge 
HugePages_Total: 0 
HugePages_Free: 0 
Hugepagesize: 2048 kB

如果有 HugePage 字样的输出内容,说明你的 OS 是支持大内存分页的。Hugepagesize 就是默认的大内存页 size。
接下来,为了让 JVM 可以调整大内存页 size,需要设置下 OS 共享内存段最大值 和 大内存页数量。

共享内存段最大值

建议这个值大于 Java Heap size,这个例子里设置了 4G 内存。

1
# echo 4294967295 > /proc/sys/kernel/shmmax

注意在 32 位操作系统上这个值不能超过 4GB

大内存页数量

1
# echo 154 > /proc/sys/vm/nr_hugepages

这个值一般是 Java 进程占用最大内存 / 单个页的大小 ,比如 java 设置 1.5G,单个页 10M,那么数量为 1536/10 = 154。
注意:因为 proc 是内存 FS,为了不让你的设置在重启后被冲掉,建议写个脚本放到 init 阶段 (rc.local)。

更简便的方法是

1
echo "vm.nr_hugepages=154" >> /etc/sysctl.conf

通过下述命令来验证设置是否生效

1
grep HugePages_Total /proc/meminfo

结果应该是你之前设置的数值 154

单个页大小调整

JVM 启用时加参数 -XX:LargePageSizeInBytes=10m

-------------本文结束感谢您的阅读-------------
Dean Wang wechat